home *** CD-ROM | disk | FTP | other *** search
- /*
- * bookmarksxbel.js
- *
- * @author david marteau <marteau.david@free.fr>
- * @copyright 2005-2006 Yoono
- */
-
-
- function ynListOfLinks( aBaseURI )
- {
- this.baseURI = aBaseURI;
- this.links = [];
- }
-
- ynListOfLinks.prototype =
- {
- copy : function( aBaseURI )
- {
- var newList = new ynListOfLinks(aBaseURI);
- for(var i=0;i<this.links.length;++i)
- newList.append(this.links[i]);
-
- return newList;
- },
-
- append : function( aURI ) {
- this.links.push(aURI);
- },
-
- contains : function( aURI )
- {
- for(var i=0;i<this.links.length;++i) {
- if(this.links[i].equals(aURI))
- return true;
- }
- return false;
- },
-
- get spec() { return this.baseURI.spec; },
-
- toString : function()
- {
- var str = "base URI: "+ this.baseURI.spec + "\n";
- for(var i=0;i<this.links.length;++i) {
- str += i+". "+this.links[i].spec+"\n";
- }
- return str;
- }
-
- };
-
-
- //====================================================
- // OPML Driver
- //====================================================
-
- function ynOPMLIOService()
- {
- this._bmUtils = new ynBookmarksUtils();
- this._yns = new Namespace(YOONO_NS);
- this._owner = "firefox-yoono-extension";
-
- this._ioSrvc = Components.classes["@mozilla.org/network/io-service;1"]
- .getService(Components.interfaces.nsIIOService);
-
- this._allowDuplicateURL = this._bmUtils.getPref("extensions.yoono.import.allowDuplicateURL",false );
- this._allowRemoteURL = this._bmUtils.getPref("extensions.yoono.import.allowRemoteURL" ,false);
- }
-
- ynOPMLIOService.prototype =
- {
-
- /*
- * import xbel xmlObject in 'root' folder
- */
- _import : function( opmlBody, root, rootLinks )
- {
- var foldersets=[[opmlBody,root,rootLinks]];
- var folderset=null;
-
- var bmUtils = this._bmUtils;
- var yns = this._yns;
- var owner = this._owner;
- var duplicate = this._allowDuplicateURL;
- var remote = this._allowRemoteURL;
-
- var opmlFileExt = /\.opml$/;
-
- const urlRes = bmUtils.getArc("URL");
- const nameRes = bmUtils.getArc("Name");
-
- /*
- * Import node as folder, handle replication
- */
-
- function importAsFolder( opml, text, description, parent, returned )
- {
- var res = null;
- var resource = null;
-
- // Find the parent folder if no duplicate allowed
- // Otherwise just add a new folder
-
- if(!duplicate) // No duplicate allowed
- resource = bmUtils.getBookmarkedResource(nameRes,text);
-
- if(!resource)
- {
- // XXX Need to set parent for setting description
- res = resource = (description ?
- bmUtils.createFolder(text,description,parent) :
- bmUtils.createFolder(text,null,null));
- }
-
- if(opml && resource)
- foldersets.push([opml,resource,returned.links]);
-
- if(returned)
- returned.value = resource;
-
- return res;
- }
-
- /*
- * Preload links
- */
-
- var resourcesLinks = this._resourcesLinks;
- var ioSrvc = this._ioSrvc;
-
- function preLoadLink( url,text,description,parent, folderLinks )
- {
- bmUtils.error("yoono:opml","preload :"+url+"\n"+folderLinks.toString());
-
- // Only link to local file allowed
- if(!remote && url.substr(0,5)!= "file:") {
- bmUtils.error("yoono:opml","remote file dropped\n"+url);
- return null;
- }
-
- var uri = ioSrvc.newURI(url, null, null);
-
- // Check for recursivity
- if(folderLinks && folderLinks.contains(uri)) {
- bmUtils.error("yoono:opml","recursive link dropped\n"+uri.spec);
- return null;
- }
-
- if(folderLinks)
- folderLinks = folderLinks.copy(uri);
- else
- folderLinks = new ynListOfLinks(uri);
-
- folderLinks.append(uri);
-
- var returned = { links: folderLinks };
- var res = importAsFolder(null,text,description,parent,returned);
-
- if(returned.value)
- resourcesLinks.push([folderLinks,returned.value]);
-
- return res;
- }
-
- // Loop over folders
-
- while(foldersets.length>0)
- {
- folderset=foldersets.shift();
-
- var folder = folderset[0];
- var parent = folderset[1];
- var folderLinks = folderset[2];
-
- var parentContainer = bmUtils.getContainer(parent);
- var numItems = 0;
-
- // Loop over child nodes
-
- for each (var element in folder.outline)
- {
- var res = null;
-
- var text = element.@text.toString();
- var description = element.@description.toString();
-
- switch(element.@type.toString())
- {
- case "include" : {
- var url = element.@url.toString();
- res = preLoadLink( url,text,description,parent,folderLinks );
- if(res) numItems++;
- } break;
-
- case "link": {
- var url = element.@url.toString();
- if(url.match(opmlFileExt))
- {
- // This is a link to an external opml resource
- // Try to import that ressource as a folder
- res = preLoadLink( url,text,description,parent,folderLinks );
- if(res) numItems++;
- }
- else
- {
- // Find a standard url ?
- // Import as standard bookmark
- if(duplicate || !bmUtils.isBookmarked(urlRes,url)) {
- var shortcutUrl = element.@yns::keywords.toString();
- res = bmUtils.createBookmark(text,url,shortcutUrl,
- description,
- null);
- numItems++;
- }
- }
- } break;
-
- case "rss" : {
- var url = element.@htmlUrl.toString();
- if(duplicate || !bmUtils.isBookmarked(urlRes,url))
- {
- var name = element.@title.toString();
- var urlfeed = element.@xmlUrl.toString();
- res = bmUtils.createLivemark(name,url,urlfeed,
- description,
- null);
- numItems++;
- }
- } break;
-
- default: {
- /*
- * Handle special types
- */
-
- if(element.@yns::type == "separator") {
- // Add separator only if items have been inserted
- // before. This prevent useless separators to be
- // displayed.
- if(numItems>0)
- res = bmUtils.createSeparator();
-
- break;
- }
-
- if(element.@yns::type == "folder") {
- // Add as folder only if it is empty
- // Because non empty <outline>'s are handled below
- if(element.outline.length()==0)
- res = importAsFolder(element,text,description,parent,{links:folderLinks});
-
- break;
- }
-
- } break;
- }
-
- if(res) {
- var index = parentContainer.IndexOf(res);
- if(index == -1)
- parentContainer.AppendElement(res);
- }
- // If there is <outline> childs then include as folder
- if(element.outline.length()>0) {
- res = importAsFolder(element,text,description,parent,{links:folderLinks});
- if(res) {
- var index = parentContainer.IndexOf(res);
- if(index == -1)
- parentContainer.AppendElement(res);
- }
- }
- }
- }
- },
-
- /*
- * export 'root' folder to opml xmlObject
- */
- _export : function( opml, root )
- {
- var bmUtils = this._bmUtils;
- var yns = this._yns;
- var owner = this._owner;
-
- const RDF = bmUtils.RDF;
- const RDFC = bmUtils.RDFC;
-
- const nsIRDFResource = Components.interfaces.nsIRDFResource;
-
- const urlRes = bmUtils.getArc("URL");
- const nameRes = bmUtils.getArc("Name");
- const descRes = bmUtils.getArc("Description");
- const keywordRes = bmUtils.getArc("ShortcutURL");
- const iconRes = bmUtils.getArc("Icon");
- const feedRes = bmUtils.getArc("FeedURL");
- const dateRes = bmUtils.getArc("BookmarkAddDate");
-
- var ds = bmUtils.BKMS;
-
- var foldersets = [[opml,root]];
- var folderset = null;
-
- var nodetree = [];
-
- while(foldersets.length>0)
- {
- folderset = foldersets.shift();
-
- var folder = folderset[0];
- var parent = folderset[1];
-
- var parentContainer = bmUtils.getContainer(parent);
- var elements = parentContainer.GetElements();
-
- var subtree = [];
-
- while (elements.hasMoreElements())
- {
- var res = elements.getNext().QueryInterface(nsIRDFResource);
-
- var separator = false;
- var isFolder = false;
- var element = null;
-
- var type = bmUtils.getType(res);
-
- switch(type)
- {
- case "Bookmark": {
- var url = bmUtils.getProperty(res,urlRes);
- var keywords = bmUtils.getProperty(res,keywordRes);
- if(keywords)
- element = <outline type="link" link={url} xmlns:yns={YOONO_NS}
- yns:keywords={keywords}/>;
- else
- element = <outline type="link" url={url}/>;
- }
- break;
-
- case "Livemark": {
- var htmlUrl = bmUtils.getProperty(res,urlRes);
- var xmlUrl = bmUtils.getProperty(res,feedRes);
- var title = bmUtils.getProperty(res,nameRes);
- element = <outline htmlUrl={htmlUrl}
- xmlUrl={xmlUrl}
- title={title}
- language="unknown"
- type="rss"/>;
- }
- break;
-
- case "Folder":
- case "ToolbarFolder":
- element = <outline yns:type="folder" xmlns:yns={YOONO_NS}/>;
- foldersets.push([element,res]);
- break;
-
- case "BookmarkSeparator":
- element = <outline yns:type="separator" xmlns:yns={YOONO_NS}/>;
- separator = true;
- break;
- }
-
- if(element)
- {
- element.@text = bmUtils.getProperty(res,nameRes);
-
- if(!separator)
- {
- var description = bmUtils.getProperty(res,descRes);
- if(description)
- element.@description = description;
- }
-
- subtree.push([element,folder]);
- }
- }
-
- nodetree = nodetree.concat(subtree.reverse());
- }
-
- while(nodetree.length>0)
- {
- var node = nodetree.pop();
- node[1].* += node[0];
- }
-
- return opml;
- },
-
- /*
- * Import opml from external link
- * XXX Should be asynchronous !
- */
- _importLink : function( uri )
- {
- try {
-
- this._bmUtils.error("yoono:opml","Loading remote file\n"+uri.spec);
-
- var channel = this._ioSrvc.newChannelFromURI( uri )
- .QueryInterface(Components.interfaces.nsIChannel);
-
- var input = channel.open();
- var sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
- .createInstance(Components.interfaces.nsIScriptableInputStream);
-
- sis.init(input);
- var buffer = sis.read(sis.available());
-
- input.close();
-
- //------------
- // Parse buffer
- // Use DOM parser for validating xml
- //------------
- var parser = new DOMParser();
- var xmldoc = parser.parseFromString(buffer,"text/xml");
-
- var root = xmldoc.documentElement;
- if ((root.tagName == "parsererror") ||
- (root.namespaceURI == "http://www.mozilla.org/newlayout/xml/parsererror.xml"))
- {
- throw(this.getString("xmlparsererror"));
- }
-
- // Get the opml node from it
- var xmlnode = xmldoc.getElementsByTagName("opml")[0];
- if(xmlnode)
- {
- var xmlstring = new XMLSerializer().serializeToString(xmlnode);
- return (new XML(xmlstring)).body;
- }
-
- } catch(e) {
- this._bmUtils.error("yoono:opml:",e);
- }
- return null;
- },
-
- /*
- * Create an opml header
- */
- createOpmlHeader : function( title,desc,ownerName,ownerEmail,ownerId )
- {
- var date = (new Date()).toUTCString();
- var opmlhead =
- <head>
- <title>{title}</title>
- <dateCreated>{date}</dateCreated>
- </head>;
-
- if(desc)
- opmlhead.* += <description>{desc}</description>;
-
- if(ownerName)
- opmlhead.* += <ownerName>{ownerName}</ownerName>;
-
- if(ownerEmail)
- opmlhead.* += <ownerEmail>{ownerEmail}</ownerEmail>;
-
- if(ownerId)
- opmlhead.* += <ownerId>{ownerId}</ownerId>;
-
- return opmlhead;
- },
-
- /*
- * Export bookmarks to OPML2 format
- */
- exportBookmarks : function ( ownerName, ownerEmail, ownerId )
- {
- var bmUtils = this._bmUtils;
-
- var opml = <opml version="2.0" xmlns:yns={YOONO_NS}/>;
- var bmRoot = bmUtils.getRoot();
-
- var title = bmUtils.getPropertyByName(bmRoot,"Name");
- var desc = bmUtils.getPropertyByName(bmRoot,"Description");
-
- opml.* += this.createOpmlHeader(title,desc,ownerName,ownerEmail,ownerId);
- opml.* += this._export(<body/>,bmRoot);
- return opml;
- },
-
- /*
- * Import bookmarks from OPML2 format
- */
- importBookmarks : function ( opml, aBookmarkFolder, baseURI )
- {
- if(!aBookmarkFolder)
- aBookmarkFolder = this._bmUtils.getRoot();
-
- this._resourcesLinks = [];
-
- this._bmUtils.beginUpdateBatch();
-
- var except;
-
- try {
-
- var baseLinks = null;
- var yns = this._yns;
-
- if(baseURI) {
- baseLinks = new ynListOfLinks(baseURI);
- baseLinks.append(baseURI);
- }
-
- // Import current node;
- this._import(opml.body,aBookmarkFolder,baseLinks);
-
- // Import remote links
- while( this._resourcesLinks.length>0 )
- {
- var resourceLink = this._resourcesLinks.shift();
- var links = resourceLink[0];
- var resource = resourceLink[1];
-
- opml = this._importLink(links.baseURI);
- this._import(opml,resource,links);
- }
- } catch(ex) {
- except = ex;
- }
-
- this._bmUtils.flush();
- this._bmUtils.endUpdateBatch();
-
- if(except)
- throw except;
- }
- };
-
-